<?php
  require_once "base.class.php";

  /**
   * This class provides methods to access a LDAP annuary.
   * Store all variavle in private.<br />
   * @param string $address The name or address of the directory server.
   * @param string $base_dn The "base dn" of the server.
   * @param string $password The password to access the server.
   *
   * @version 1.0 beta
   * @author Dany Mottier
   * @see <a href="http://fr2.php.net/manual/en/ldap.using.php">online documentation</a>
   */
  class LDAP extends Base {
    /** @var string The name or address of the directory server you will use .*/
    private $address = "";

    /** @var integer The port to connect to.*/
    private $port = 389;

    /**
     * @var string The "base dn" of the server (the part of the world directory
     * that is held on this server, which could be "o=My Company,c=US").
     */
    private $base_dn = "";

    /** @var string The login to connect to the server.*/
    private $login = "";

    /**
     * @var string Whether you need a password to access the server (many
     * servers will provide read access for an "anonymous bind" but require a
     * password for anything else)
     */
    private $password = "";

    /** @var resource The positive LDAP link identifier return when connected. */
    private $Handle = NULL;

    /**
     * Store all variavle in private.<br />
     * @param string $address The name or address of the directory server.
     * @param string $base_dn The "base dn" of the server.
     * @param string $password The password to access the server.
     */
    public function __construct($address, $base_dn, $password = "") {
      $this->address  = $address;
      $this->base_dn  = $base_dn;
      $this->password = $password;
    }

    /**
     * Returns the address of the annuary.<br />
     * @return string The address.
     */
    public function getAddress() {
      return $this->address;
    }

    /**
     * Returns the port to connect to.<br />
     * @return integer The port.
     */
    public function getPort() {
      return $this->port;
    }

    /**
     * Returns the base dn of the server.<br />
     * @return string The base dn of the server.
     */
    public function getBaseDN() {
      return $this->base_dn;
    }

    /**
     * Returns the login to connect to the server.<br />
     * @return string The login.
     */
    public function getLogin() {
      return $this->login;
    }

    /**
     * Returns the password to access the server.<br />
     * @return string The password.
     */
    public function getPassword() {
      return $this->password;
    }

    /**
     * Returns the LDAP error message of the last LDAP command.<br />
     * Returns the string error message explaining the error generated by the
     * last LDAP command for the current link identifier.<br />
     * While LDAP errno numbers are standardized, different libraries return
     * different or even localized textual error messages.<br />
     * Never check for a specific error message text, but always use an error number to check.<br /><br />
     * Unless you lower your warning level in your php.ini sufficiently or
     * prefix your LDAP commands with @ (at) characters to suppress warning
     * output, the errors generated will also show up in your HTML output.<br />
     *
     * @return string Returns string error message.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-error.php">ldap_error()</a>
     */
    public function getError() {
      return ldap_error($this->Handle);
    }

    /**
     * Returns the LDAP error number of the last LDAP command.<br />
     * Returns the standardized error number returned by the last LDAP command.<br />
     * This number can be converted into a textual error message using getErrorString().<br />
     *
     * @return integer Return the LDAP error number of the last LDAP command for this link.<br /><br />
     *
     * @see getErrorString()
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-errno.php">ldap_errno()</a>
     */
    public function getErrorNumber() {
      return ldap_errno($this->Handle);
    }

    /**
     * Convert and returns LDAP error number into string error message.<br />
     * Returns the string error message explaining the error internal number.<br />
     * While LDAP errno numbers are standardized, different libraries return
     * different or even localized textual error messages.<br />
     * Never check for a specific error message text, but always use an error number to check.<br />
     *
     * @return string The error number.<br /><br />
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-err2str.php">ldap_err2str()</a>
     */
    public function getErrorString() {
      return ldap_err2str($this->getErrorNumber());
    }

    /**
     * Sets the address of th annuary.<br />
     * @param string $value The address/
     */
    public function setAddress($value) {
      $this->address = $value;
    }

    /**
     * Sets the port to connect to.<br />
     * @param integer $value The port to connect to.
     */
    public function setPort($value) {
      $this->port = $value;
    }

    /**
     * Sets the base dn of the server.<br />
     * @param string $value The base dn.
     */
    public function setBaseDN($value) {
      $this->base_dn = $value;
    }

    /**
     * Sets the login to connect to the server.<br />
     * @param string $value The login.
     */
    public function setLogin($value) {
      $this->login = $value;
    }

    /**
     * Sets the password to access the server.<br />
     * @param string $value The password.
     */
    public function setPassword($value) {
      $this->password = $value;
    }

    /**
     * Add entries to LDAP directory.<br />
     *
     * @param string $dn The distinguished name of an LDAP entity.
     * @param array $entry An array that specifies the information about the
     * entry.<br />
     * The values in the entries are indexed by individual attributes.<br />
     * In case of multiple values for an attribute, they are indexed using
     * integers starting with 0.
     *
     * @return boolean Returns TRUE on success or FALSE on failure.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-add.php">ldap_add()</a>
     */
    public function Add($dn, $entry) {
      return ldap_add($this->Handle, $dn, $entry);
    }

    /**
     * Add attribute values to current attributes.<br />
     * Adds one or more attributes to the specified dn.<br />
     * It performs the modification at the attribute level as opposed to the
     * object level.<br />
     * Object-level additions are done by the ldap_add() function.<br />
     *
     * @param string $dn The distinguished name of an LDAP entity.
     * @param array $entry No documentation is provided.
     *
     * @return boolean Returns TRUE on success or FALSE on failure.
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-mod-add.php">ldap_mod_add()</a>
     */
    public function AddAttribute($dn, $entry) {
      return ldap_mod_add($this->Handle, $dn, $entry);
    }

    /**
     * Bind to LDAP directory.<br />
     * @param boolean $anonymous Define if the connection should be anonymous or not.
     * @return boolean Returns TRUE on success or FALSE on failure.<br /><br />
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-bind.php">ldap_bind()</a>
     */
    public function Bind($anonymous = FALSE) {
      if ($anonymous)
        return ldap_bind($this->Handle);
      else
        return ldap_bind($this->Handle, $this->login, $this->password);
    }

    /**
     * Bind to LDAP directory using SASL.<br />
     *
     * @param string $dn No documentation is provided.
     * @param string $password No documentation is provided.
     * @param string $sasl_mech No documentation is provided.
     * @param string $sasl_realm No documentation is provided.
     * @param string $sasl_authc_id No documentation is provided.
     * @param string $sasl_authz_id No documentation is provided.
     * @param string $props No documentation is provided.
     *
     * @return boolean Returns TRUE on success or FALSE on failure.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-sasl-bind.php">ldap_sasl_bind()</a>
     */
    public function BindSASL($dn = "", 
                             $password = "",
                             $sasl_mech = "",
                             $sasl_realm = "",
                             $sasl_authc_id = "",
                             $sasl_authz_id = "", 
                             $props = "") {
      if (! empty($props))
        return ldap_sasl_bind($this->Handle, $dn, $password, $sasl_mech,
                              $sasl_realm, $sasl_authc_id, $sasl_authz_id, $props);
      else
        if (! empty($sasl_authz_id))
          return ldap_sasl_bind($this->Handle, $dn, $password, $sasl_mech,
                              $sasl_realm, $sasl_authc_id, $sasl_authz_id);
        else
          if (! empty($sasl_authc_id))
            return ldap_sasl_bind($this->Handle, $dn, $password, $sasl_mech,
                              $sasl_realm, $sasl_authc_id);
          else
            if (! empty($sasl_realm))
              return ldap_sasl_bind($this->Handle, $dn, $password, $sasl_mech,
                              $sasl_realm);
            else
              if (! empty($sasl_mech))
                return ldap_sasl_bind($this->Handle, $dn, $password, $sasl_mech);
              else
                if (! empty($password))
                  return ldap_sasl_bind($this->Handle, $dn, $password);
                else
                  if (! empty($dn))
                    return ldap_sasl_bind($this->Handle, $dn);
                  else
                    return ldap_sasl_bind($this->Handle);
    }

    /**
     * Alias of Unbind()<br />
     * @see Unbind()
     */
    public function Close() {
      return $this->Unbind();
    }

    /**
     * Compare value of attribute found in entry specified with DN.<br />
     * @param string $dn The distinguished name of an LDAP entity.
     * @param string $attribute The attribute name.
     * @param string $value The compared value.
     * @return mixed Returns TRUE if value  matches otherwise returns FALSE. Returns -1 on error.<br /><br />
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-compare.php">ldap_compare()</a>
     */
    public function Compare($dn, $attribute, $value) {
      return ldap_compare($this->Handle, $dn, $attribute, $value);
    }

    /**
     * Connect to an LDAP server.<br />
     * Establishes a connection to a LDAP server on private hostname and port.<br />
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-connect.php">ldap_connect()</a>
     */
    public function Connect() {
      $this->Handle = ldap_connect($this->address, $this->port);
    }

    /**
     * Count the number of entries in a search.<br />
     * @param resource $Result The internal LDAP result.
     * @return mixed Returns number of entries in the result or FALSE on error.<br /><br />
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-count-entries.php">ldap_count_entries()</a>
     */
    public function CountEntries($Result) {
      return ldap_count_entries($this->Handle, $Result);
    }

    /**
     * Delete an entry from a directory.<br />
     * Deletes a particular entry in LDAP directory.<br />
     * @param string $dn The distinguished name of an LDAP entity.
     * @return boolean Returns TRUE on success or FALSE on failure.<br /><br />
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-delete.php">ldap_delete()</a>
     */
    public function Delete($dn) {
      return ldap_delete($this->Handle, $dn);
    }

    /**
     * Delete attribute values from current attributes.<br />
     * Removes one or more attributes from the specified dn.<br />
     * It performs the modification at the attribute level as opposed to the
     * object level.<br />Object-level deletions are done by the ldap_delete() function.<br />
     *
     * @param string $dn The distinguished name of an LDAP entity.
     * @param array $entry No documentation is provided.
     *
     * @return bolean Returns TRUE on success or FALSE on failure.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-mod-del.php">ldap_mod_del()</a>
     */
    public function DeleteAttribute($dn, $entry) {
      return ldap_mod_del($this->Handle, $dn, $entry);
    }

    /**
     * Convert DN to User Friendly Naming format.<br />
     * Turns the specified $dn, into a more user-friendly form, stripping off type names.<br />
     * @param string $dn The distinguished name of an LDAP entity.
     * @return string Returns the user friendly name.<br /><br />
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-dn2ufn.php">ldap_dn2ufn()</a>
     */
    public function DNToUFN($dn) {
      return ldap_dn2ufn($dn);
    }

    /**
     * Splits DN into its component parts.<br />
     * Splits the DN returned by ldap_get_dn() and breaks it up into its
     * component parts.<br />Each part is known as Relative Distinguished Name, or RDN.<br />
     *
     * @param string $dn The distinguished name of an LDAP entity.
     * @param integer $with_attribute Used to request if the RDNs are returned
     * with only values or their attributes as well.<br />
     * To get RDNs with the attributes (i.e. in attribute=value format) set
     * $with_attribute to 0 and to get only values set it to 1.
     *
     * @return array Returns an array of all DN components.<br />
     * The first element in this array has count key and represents the number 
     * of returned values, next elements are numerically indexed DN components. <br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-explode-dn.php">ldap_explode_dn()</a>
     */
    public function ExplodeDN($dn, $with_attribute) {
      return ldap_explode_dn($dn, $with_attribute);
    }

    /**
     * Returns first attribute.<br />
     * Gets the first attribute in the given entry.<br />
     * Remaining attributes are retrieved by calling NextAttribute() successively.<br />
     * Similar to reading entries, attributes are also read one by one from a particular entry.<br />
     *
     * @param resource $Result No documentation is provided.
     *
     * @return mixed Returns the first attribute in the entry on success and FALSE on error.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-first-attribute.php">ldap_first_attribute()</a>
     */
    public function FirstAttribute($Result) {
      return ldap_first_attribute($this->Handle, $Result);
    }

    /**
     * Returns first result id.<br />
     * Returns the entry identifier for first entry in the result.<br />
     * This entry identifier is then supplied to NextEntry() routine to get
     * successive entries from the result.<br />
     * Entries in the LDAP result are read sequentially using the FirstEntry()
     * and NextEntry() functions.<br />
     *
     * @param resource $Result No documentation is provided.
     *
     * @return mixed Returns the result entry identifier for the first entry on
     * success and FALSE on error.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-first-entry.php">ldap_first_entry()</a>
     */
    public function FirstEntry($Result) {
      return ldap_first_entry($this->Handle, $Result);
    }

    /**
     * Returns first reference.<br />
     * This function is currently not documented; only its argument list is available.<br />
     * @param resource $Resource No documentation is provided.
     * @return resource No documentation is provided.<br /><br />
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-first-reference.php">ldap_first_reference()</a>
     */
    public function FirstReference($Resource) {
      return ldap_first_reference($this->Handle, $Resource);
    }

    /**
     * Frees result memory.<br />
     * Frees up the memory allocated internally to store the result.<br />
     * All result memory will be automatically freed when the script terminates.<br /><br />
     * Typically all the memory allocated for the LDAP result gets freed at the
     * end of the script.<br />
     * In case the script is making successive searches which return large
     * result sets, FreeResult() could be called to keep the runtime memory
     * usage by the script low.<br />
     *
     * @param resource $Result No documentation is provided.
     *
     * @return boolean Returns TRUE on success or FALSE on failure.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-free-result.php">ldap_free_result()</a>
     */
    public function FreeResult($Result) {
      return ldap_free_result($Result);
    }

    /**
     * Gets attributes from a search result entry.<br />
     * Reads attributes and values from an entry in the search result.<br />
     * Having located a specific entry in the directory, you can find out what
     * information is held for that entry by using this call.<br />
     * You would use this call for an application which "browses" directory
     * entries and/or where you do not know the structure of the directory entries.<br />
     * In many applications you will be searching for a specific attribute such
     * as an email address or a surname, and won't care what other data is held.<br />
     *
     * @param resource $Result No documentation is provided.
     * @return mixed Returns a complete entry information in a multi-dimensional
     * array on success and FALSE on error.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-get-attributes.php">ldap_get_attributes()</a>
     */
    public function GetAttributes($Result) {
      return ldap_get_attributes($this->Handle, $Result);
    }

    /**
     * Gets all binary values from a result entry.<br />
     * Reads all the values of the attribute in the entry in the result.<br />
     * This function is used exactly like GetValues() except that it handles 
     * binary data and not string data.<br />
     * 
     * @param resource $Result No documentation is provided.
     * @param string $attribute No documentation is provided.
     * 
     * @return mixed Returns an array of values for the attribute on success and
     * FALSE on error.<br />
     * Individual values are accessed by integer index in the array.<br />
     * The first index is 0.<br />
     * The number of values can be found by indexing "count" in the resultant array.<br /><br />
     * 
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-get-values-len.php">ldap_get_values_len()</a>
     */
    public function GetBinaryValues($Result, $attribute) {
      return ldap_get_values_len($this->Handle, $Result, $attribute);
    }

    /**
     * Gets the DN of a result entry.<br />
     * Finds out the DN of an entry in the result.<br />
     *
     * @param resource $Result No documentation is provided.
     *
     * @return mixed Returns the DN of the result entry and FALSE on error.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-get-dn.php">ldap_get_dn()</a>
     */
    public function GetDN($Result) {
      return ldap_get_dn($this->Handle, $Result);
    }

    /**
     * Gets all result entries.<br />
     * Reads multiple entries from the given result, and then reading the
     * attributes and multiple values.<br />
     *
     * @param resource $Result No documentation is provided.
     *
     * @return mixed Returns a complete result information in a multi-dimensional
     * array on success and FALSE on error.<br />
     * The structure of the array is as follows.<br />
     * The attribute index is converted to lowercase.<br />
     * (Attributes are case-insensitive for directory servers, but not when
     * used as array indices.)<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-get-entries.php">ldap_get_entries()</a>
     */
    public function GetEntries($Result) {
      return ldap_get_entries($this->Handle, $Result);
    }

    /**
     * Gets the current value for given option.<br />
     *
     * @param integer $option The parameter option  can be one of : LDAP_OPT_DEREF,
     * LDAP_OPT_SIZELIMIT, LDAP_OPT_TIMELIMIT, LDAP_OPT_NETWORK_TIMEOUT,
     * LDAP_OPT_PROTOCOL_VERSION, LDAP_OPT_ERROR_NUMBER, LDAP_OPT_REFERRALS,
     * LDAP_OPT_RESTART, LDAP_OPT_HOST_NAME, LDAP_OPT_ERROR_STRING,
     * LDAP_OPT_MATCHED_DN, LDAP_OPT_SERVER_CONTROLS or LDAP_OPT_CLIENT_CONTROLS.<br />
     *
     * @return mixed The value of the option of FALSE on failure.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-get-option.php">ldap_get_option()</a>
     */
    public function GetOption($option) {
      $return = NULL;

      if (ldap_get_option($this->Handle, $option, $return))
        return $return;
      else
        return FALSE;
    }

    /**
     * Get all values from a result entry.<br />
     * Reads all the values of the attribute in the entry in the result.<br />
     * You application will either be hard coded to look for certain attributes
     * (such as "surname" or "mail") or you will have to use the GetAttributes()
     * call to work out what attributes exist for a given entry.<br />
     *
     * @param resource $Result No documentation is provided.
     * @param string $attribute No documentation is provided.
     *
     * @return Returns an array of values for the attribute on success and FALSE
     * on error.<br />
     * The number of values can be found by indexing "count" in the resultant
     * array.<br />
     * Individual values are accessed by integer index in the array.<br />
     * The first index is 0.<br />
     * LDAP allows more than one entry for an attribute, so it can, for example,
     * store a number of email addresses for one person's directory entry all
     * labeled with the attribute "mail".<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-get-values.php">ldap_get_values()</a>
     */
    public function GetValues($Result, $attribute) {
      return ldap_get_values($this->Handle, $Result, $attribute);
    }

    /**
     * Single-level search.<br />
     * Performs the search for a specified filter  on the directory with the
     * scope LDAP_SCOPE_ONELEVEL.<br />
     * LDAP_SCOPE_ONELEVEL means that the search should only return information
     * that is at the level immediately below the base_dn  given in the call.<br />
     * (Equivalent to typing "ls" and getting a list of files and folders in
     * the current working directory.)<br />
     *
     * @param string $dn The base DN for the directory.
     * @param string $filter No documentation is provided.
     *
     * @param array $attributes An array of the required attributes, e.g.
     * array("mail", "sn", "cn").<br />Note that the "dn" is always returned
     * irrespective of which attributes types are requested.<br />
     * Using this parameter is much more efficient than the default action
     * (which is to return all attributes and their associated values).<br />
     * The use of this parameter should therefore be considered good practice.

     * @param integer $attrsonly Should be set to 1 if only attribute types are
     * wanted.<br />If set to 0 both attributes types and attribute values are
     * fetched which is the default behaviour.
     *
     * @param integer $sizelimit Enables you to limit the count of entries
     * fetched.<br />Setting this to 0 means no limit.
     *
     * @param integer $timelimit Sets the number of seconds how long is spend
     * on the search.<br />Setting this to 0 means no limit.
     *
     * @param integer $deref Specifies how aliases should be handled during the
     * search.<br />It can be one of the following :<br /><br />
     * LDAP_DEREF_NEVER - (default) aliases are never dereferenced.<br />
     * LDAP_DEREF_SEARCHING - aliases should be dereferenced during the search
     * but not when locating the base object of the search.<br />
     * LDAP_DEREF_FINDING - aliases should be dereferenced when locating the
     * base object but not during the search.<br />
     * LDAP_DEREF_ALWAYS - aliases should be dereferenced always.
     *
     * @return mixed Returns a search result identifier or FALSE on error.<br /><br />
     * 
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-list.php">ldap_list()</a>
     */
    public function ListLevels($dn, $filter, $attributes = NULL,
                                            $attrsonly = -1,
                                            $sizelimit = -1,
                                            $timelimit = -1,
                                            $deref = -1) {
      if (! empty($deref) && $deref > -1)
        return ldap_list($this->Handle, $dn, $filter, $attributes, $attrsonly, $sizelimit, $timelimit, $deref);
      else
        if (! empty($timelimit) && $timelimit > -1)
          return ldap_list($this->Handle, $dn, $filter, $attributes, $attrsonly, $sizelimit, $timelimit);
        else
          if (! empty($sizelimit) && $sizelimit > -1)
            return ldap_list($this->Handle, $dn, $filter, $attributes, $attrsonly, $sizelimit);
          else
            if (! empty($attrsonly) && $attrsonly > -1)
              return ldap_list($this->Handle, $dn, $filter, $attributes, $attrsonly);
            else
              if (! empty($attributes))
                return ldap_list($this->Handle, $dn, $filter, $attributes);
              else
                return ldap_list($this->Handle, $dn, $filter);
    }

    /**
     * Modify an LDAP entry.<br />
     * Modify the existing entries in the LDAP directory.<br />
     * The structure of the entry is same as in Add().<br />
     *
     * @param string $dn The distinguished name of an LDAP entity.
     * @param array $entry No documentation is provided.
     *
     * @return boolean Returns TRUE on success or FALSE on failure.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-modify.php">ldap_modify()</a>
     */
    public function Modify($dn, $entry) {
      return ldap_modify($this->Handle, $dn, $entry);
    }

    /**
     * Get the next attribute in result.<br />
     * Retrieves the attributes in an entry.<br />
     * The first call to NextAttribute() is made with the $Result returned from 
     * FirstAttribute().<br />
     * 
     * @param resource $Result No documentation is provided.
     * 
     * @return mixed Returns the next attribute in an entry on success and 
     * FALSE on error.<br /><br />
     * 
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-next-attribute.php">ldap_next_attribute()</a>
     */
    public function NextAttribute($Result) {
      return ldap_next_attribute($this->Handle, $Result);
    }

    /**
     * Get next result entry.<br />
     * Retrieve the entries stored in the result.<br />
     * Successive calls to the NextEntry() return entries one by one till there
     * are no more entries.<br />
     * The first call to NextEntry() is made after the call to FirstEntry() with
     * the $Result as returned from the FirstEntry(). <br />
     *
     * @param resource $Resource No documentation is provided.
     *
     * @return mixed Returns entry identifier for the next entry in the result
     * whose entries are being read starting with ldap_first_entry().<br />
     * If there are no more entries in the result then it returns FALSE.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-next-entry.php">ldap_next_entry()</a>
     */
    public function NextEntry($Resource) {
      return ldap_next_entry($this->Handle, $Resource);
    }

    /**
     * Get next reference.<br />
     * @param resource $link No documentation is provided.
     * @param resource $entry No documentation is provided.
     * @return resource No documentation is provided.<br /><br />
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-next-reference.php">ldap_next_reference()</a>
     */
    public function NextReference($link, $entry) {
      return ldap_next_reference($link, $entry);
    }

    /**
     * Extract information from reference entry.<br />
     * @param resource $link No documentation is provided.
     * @param array $entry No documentation is provided.
     * @return boolean No documentation is provided.<br /><br />
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-parse-reference.php">ldap_parse_reference()</a>
     */
    public function ParseReference($link, $entry) {
      $return = NULL;

      if (ldap_parse_reference($link, $entry, $return))
        return $return;
      else
        return FALSE;
    }

    /** Not implemented. */
    public function ParseResult() {}

    /**
     * Read an entry.<br />
     * Performs the search for a specified filter on the directory with the
     * scope LDAP_SCOPE_BASE. So it is equivalent to reading an entry from
     * the directory.<br />
     *
     * @param string $dn The base DN for the directory.
     *
     * @param string $filter An empty filter is not allowed.<br />
     * If you want to retrieve absolutely all information for this entry, use a
     * filter of objectClass=*.<br />
     * If you know which entry types are used on the directory server, you might
     * use an appropriate filter such as objectClass=inetOrgPerson.
     *
     * @param array $attributes An array of the required attributes, e.g.
     * array("mail", "sn", "cn").<br />Note that the "dn" is always returned
     * irrespective of which attributes types are requested.<br /><br />
     * Using this parameter is much more efficient than the default action
     * (which is to return all attributes and their associated values).<br />
     * The use of this parameter should therefore be considered good practice.

     * @param integer $attrsonly Should be set to 1 if only attribute types are
     * wanted.<br />If set to 0 both attributes types and attribute values are
     * fetched which is the default behaviour.
     *
     * @param integer $sizelimit Enables you to limit the count of entries
     * fetched.<br />Setting this to 0 means no limit.
     *
     * @param integer $timelimit Sets the number of seconds how long is spend
     * on the search. Setting this to 0 means no limit.
     *
     * @param integer $deref Specifies how aliases should be handled during the
     * search.<br />It can be one of the following :<br /><br />
     * LDAP_DEREF_NEVER - (default) aliases are never dereferenced.<br />
     * LDAP_DEREF_SEARCHING - aliases should be dereferenced during the search 
     * but not when locating the base object of the search.<br />
     * LDAP_DEREF_FINDING - aliases should be dereferenced when locating the 
     * base object but not during the search.<br />
     * LDAP_DEREF_ALWAYS - aliases should be dereferenced always.
     *
     * @return mixed Returns a search result identifier or FALSE on error.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-read.php">ldap_read()</a>
     */
    public function Read($dn, $filter, $attributes = NULL,
                                       $attrsonly = -1,
                                       $sizelimit = -1,
                                       $timelimit = -1,
                                       $deref = -1) {
      if (! empty($deref) && $deref > -1)
        return ldap_read($this->Handle, $dn, $filter, $attributes, $attrsonly, $sizelimit, $timelimit, $deref);
      else
        if (! empty($timelimit) && $timelimit > -1)
          return ldap_read($this->Handle, $dn, $filter, $attributes, $attrsonly, $sizelimit, $timelimit);
        else
          if (! empty($sizelimit) && $sizelimit > -1)
            return ldap_read($this->Handle, $dn, $filter, $attributes, $attrsonly, $sizelimit);
          else
            if (! empty($attrsonly) && $attrsonly > -1)
              return ldap_read($this->Handle, $dn, $filter, $attributes, $attrsonly);
            else
              if (! empty($attributes))
                return ldap_read($this->Handle, $dn, $filter, $attributes);
              else
                return ldap_read($this->Handle, $dn, $filter);
    }
    
    /**
     * Modify the name of an entry.<br />
     * The entry specified by dn  is renamed/moved.<br />
     * 
     * @param string $dn The distinguished name of an LDAP entity. 
     * @param string $newrdn The new RDN. 
     * @param string $newparent The new parent/superior entry. 
     * @param boolean $deleteoldrdn If TRUE the old RDN value(s) is removed, 
     * else the old RDN value(s) is retained as non-distinguished values of the entry. 
     * 
     * @return boolean Returns TRUE on success or FALSE on failure. <br /><br />
     * 
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-rename.php">ldap_rename()</a>
     */
    public function Rename($dn, $newrdn, $newparent, $deleteoldrdn = TRUE) {
      return ldap_rename($this->Handle, $dn, $newrdn, $newparent, $deleteoldrdn);
    }

    /**
     * Replace attribute values with new ones.<br />
     * Replaces one or more attributes from the specified dn.<br />
     * It performs the modification at the attribute level as opposed to the
     * object level.<br />
     * Object-level modifications are done by the ldap_modify() function.<br />
     *
     * @param string $dn The distinguished name of an LDAP entity.
     * @param array $entry No documentation is provided.
     *
     * @return Returns TRUE on success or FALSE on failure.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-mod-replace.php">ldap_mod_replace()</a>
     */
    public function ReplaceAttribute($dn, $entry) {
      return ldap_mod_replace($this->Handle, $dn, $entry);
    }

    /**
     * Search LDAP tree.<br />
     * Performs the search for a specified filter on the directory with the
     * scope of LDAP_SCOPE_SUBTREE.<br />
     * This is equivalent to searching the entire directory.<br /><br />
     * From 4.0.5 on it's also possible to do parallel searches.<br />
     * To do this you use an array of link identifiers, rather than a single
     * identifier, as the first argument.<br />
     * If you don't want the same base DN and the same filter for all the
     * searches, you can also use an array of base DNs and/or an array of
     * filters.<br />
     * Those arrays must be of the same size as the link identifier array since
     * the first entries of the arrays are used for one search, the second
     * entries are used for another, and so on. When doing parallel searches an
     * array of search result identifiers is returned, except in case of error,
     * then the entry corresponding to the search will be FALSE.<br />
     * This is very much like the value normally returned, except that a result
     * identifier is always returned when a search was made.<br />
     * There are some rare cases where the normal search returns FALSE while
     * the parallel search returns an identifier.<br />
     *
     * @param string $dn The base DN for the directory.
     *
     * @param string $filter The search filter can be simple or advanced, using
     * boolean operators in the format described in the LDAP documentation
     * (see the » Netscape Directory SDK for full information on filters).
     *
     * @param array $attributes An array of the required attributes, e.g.
     * array("mail", "sn", "cn"). Note that the "dn" is always returned
     * irrespective of which attributes types are requested.<br /><br />
     * Using this parameter is much more efficient than the default action
     * (which is to return all attributes and their associated values).<br />
     * The use of this parameter should therefore be considered good practice.

     * @param integer $attrsonly Should be set to 1 if only attribute types are
     * wanted.<br />If set to 0 both attributes types and attribute values are
     * fetched which is the default behaviour.
     *
     * @param integer $sizelimit Enables you to limit the count of entries
     * fetched.<br />Setting this to 0 means no limit.
     *
     * @param integer $timelimit Sets the number of seconds how long is spend
     * on the search. Setting this to 0 means no limit.
     *
     * @param integer $deref Specifies how aliases should be handled during the
     * search. It can be one of the following :<br /><br />
     * LDAP_DEREF_NEVER - (default) aliases are never dereferenced.<br />
     * LDAP_DEREF_SEARCHING - aliases should be dereferenced during the search
     * but not when locating the base object of the search.<br />
     * LDAP_DEREF_FINDING - aliases should be dereferenced when locating the
     * base object but not during the search.<br />
     * LDAP_DEREF_ALWAYS - aliases should be dereferenced always.
     *
     * @return mixed Returns a search result identifier or FALSE on error.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-search.php">ldap_search()</a>
     */
    public function Search($dn,
                           $filter,
                           $attributes = NULL,
                           $attrsonly = -1,
                           $sizelimit = -1, 
                           $timelimit = -1,
                           $deref = -1) {
      if ($deref > -1)
        return ldap_search($this->Handle, $dn, $filter, $attributes, $attrsonly, $sizelimit, $timelimit, $deref);
      else
        if ($timelimit > -1)
          return ldap_search($this->Handle, $dn, $filter, $attributes, $attrsonly, $sizelimit, $timelimit);
        else
          if ($sizelimit > -1)
            return ldap_search($this->Handle, $dn, $filter, $attributes, $attrsonly, $sizelimit);
          else
            if ($attrsonly > -1)
              return ldap_search($this->Handle, $dn, $filter, $attributes, $attrsonly);
            else
              if (! empty($attributes))
                return ldap_search($this->Handle, $dn, $filter, $attributes);
              else
                return ldap_search($this->Handle, $dn, $filter);

    }

    /**
     * Set the value of the given option.<br />
     * Sets the value of the specified option to be $newval.<br />
     *
     * @param integer $otion  The parameter option  can be one of :<br /><br />
     * LDAP_OPT_DEREF 	integer <br />
     * LDAP_OPT_SIZELIMIT 	integer<br />
     * LDAP_OPT_TIMELIMIT 	integer<br />
     * LDAP_OPT_NETWORK_TIMEOUT 	integer<br />
     * LDAP_OPT_PROTOCOL_VERSION 	integer<br />
     * LDAP_OPT_ERROR_NUMBER 	integer<br />
     * LDAP_OPT_REFERRALS 	bool<br />
     * LDAP_OPT_RESTART 	bool<br />
     * LDAP_OPT_HOST_NAME 	string<br />
     * LDAP_OPT_ERROR_STRING 	string<br />
     * LDAP_OPT_MATCHED_DN 	string<br />
     * LDAP_OPT_SERVER_CONTROLS 	array<br />
     * LDAP_OPT_CLIENT_CONTROLS 	array<br />
     *
     * LDAP_OPT_SERVER_CONTROLS and LDAP_OPT_CLIENT_CONTROLS require a list of
     * controls, this means that the value must be an array of controls.<br />
     * A control consists of an oid identifying the control, an optional value,
     * and an optional flag for criticality.<br />
     * In PHP a control is given by an array containing an element with the key
     * oid and string value, and two optional elements.<br />
     * The optional elements are key value with string value and key iscritical
     * with boolean value. iscritical defaults to FALSE  if not supplied. See »
     * draft-ietf-ldapext-ldap-c-api-xx.txt for details.<br />
     * See also the second example below.
     *
     * @param mixed $newval The new value for the specified option.
     *
     * @return boolean Returns TRUE on success or FALSE on failure.<br /><br />
     *
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-set-option.php">ldap_set_option()</a>
     */
    public function SetOption($otion, $newval) {
      return ldap_set_option($this->Handle, $otion, $newval);
    }

    /** Not yet implemented. */
    public function SetRebindProc($callback) {}

    /**
     * Sort LDAP result entries.<br />
     * @param resource $Result No documentation is provided.
     * @param string $sort_filter No documentation is provided.
     * @return boolean No documentation is provided.<br /><br />
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-sort.php">ldap_sort()</a>
     */
    public function Sort($Result, $sort_filter) {
      return ldap_sort($this->Handle, $Result, $sort_filter);
    }

    /**
     * Start TLS.<br />
     * @return boolean No documentation is provided.<br /><br />
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-start-tls.php">ldap_start_tls()</a>
     */
    public function StartTLS() {
      return ldap_start_tls($this->Handle);
    }

    /**
     * Unbind from LDAP directory.<br />
     * @return boolean Returns TRUE on success or FALSE on failure.<br /><br />
     * @see <a href="http://fr2.php.net/manual/en/function.ldap-unbind.php">ldap_unbind()</a>
     */
    public function Unbind() {
      return ldap_unbind($this->Handle);
    }
  }
?>
